package com.fjwt.gz.core.utils;

import cn.hutool.core.date.DateUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.fjwt.gz.core.entity.SmsTemplateEntity;
import com.fjwt.gz.core.exception.BizException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;

import java.security.MessageDigest;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
public class LLSMSUtil {
  

    /**
     * 联麓发送短信
     * @param smsTemplate
     * @param phones
     * @param params
     */
    public static void send(SmsTemplateEntity smsTemplate, List<String> phones, List<String> params) {
        log.info("联麓发送短信参数：smsTemplate：{}，params：{}，phones：{}", JSON.toJSONString(smsTemplate), params, phones);
        if (ObjectUtils.isEmpty(phones) || ObjectUtils.isEmpty(params)) {
            throw new BizException("请输入要发送的手机号和短信内容");
        }
        if (ObjectUtils.isEmpty(smsTemplate) || ObjectUtils.isEmpty(smsTemplate.getTemplateId())
                || ObjectUtils.isEmpty(smsTemplate.getMchId()) || ObjectUtils.isEmpty(smsTemplate.getAppId()) || ObjectUtils.isEmpty(smsTemplate.getAppKey())) {
            throw new BizException("短信发送参数异常");
        }
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("AppId", smsTemplate.getAppId());
        jsonObject.put("MchId", smsTemplate.getMchId());
        jsonObject.put("TemplateId", smsTemplate.getTemplateId());
        jsonObject.put("Type", smsTemplate.getType());
        jsonObject.put("SignType", "MD5");
        jsonObject.put("TimeStamp", DateUtil.date().getTime());
        jsonObject.put("Version", "1.1.0");
        jsonObject.put("PhoneNumberSet", phones);
        jsonObject.put("TemplateParamSet", params);
        try {
            jsonObject.put("Signature", sign(jsonObject, smsTemplate.getAppKey()));
        } catch (Exception e) {
            log.info("短信签名异常：", e);
            throw new BizException(e.getMessage());
        }

        log.info("联麓发送短信请求参数：{}", jsonObject.toJSONString());
        // 发送短信
        HttpResponse response = HttpRequest.post("https://apis.shlianlu.com/sms/trade/template/send")
                .header("Accept", "application/json")
                .header("Content-Type", "application/json;charset=utf-8")
                .timeout(20000)
                .body(jsonObject.toJSONString())
                .execute();
        log.info("联麓发送短信请求结果，response：{}", JSON.toJSONString(response));
        JSONObject bodyJson = JSONObject.parseObject(response.body());
        log.info("联麓发送短信返回参数：{}", JSON.toJSONString(bodyJson));
        if (200 == response.getStatus()) {
            if (!"00".equals(bodyJson.getString("status"))) {
                throw new BizException(bodyJson.getString("message"));
            }else {
                log.info("联麓短信发送成功");
            }
        }else {
            throw new BizException("短信发送异常");
        }
    }

    // 短信签名
    private static String sign(Map<String, Object> params, String appKey) throws Exception {
        // 请求中所有参数名排序，参数过滤后按顺序拼接
        String str = params.entrySet().stream()
                .filter(e -> (!e.getKey().equals("Signature")
                        && !e.getKey().equals("SessionContext")
                        && !e.getKey().equals("PhoneNumberSet")
                        && !e.getKey().equals("SessionContextSet")
                        && !e.getKey().equals("ContextParamSet")
                        && !e.getKey().equals("TemplateParamSet")
                        && !e.getKey().equals("PhoneList")
                        && !e.getKey().equals("phoneSet")
                        &&  e.getValue() != null
                        && !e.getValue().toString().isEmpty()
                ))
                .sorted(Map.Entry.comparingByKey())
                .map(e -> e.getKey() + "=" + e.getValue())
                // 结尾拼接上appkey
                .collect(Collectors.joining("&")) + "&key=" + appKey;
        // 拼接后字符串MD5加密
        MessageDigest md = MessageDigest.getInstance("MD5");
        md.update(str.getBytes("UTF-8"));
        byte[] digest = md.digest();
        StringBuilder sb = new StringBuilder();
        for (byte b : digest) {
            sb.append(String.format("%02x", b & 0xff));
        }
        // 加密后大写
        return sb.toString().toUpperCase();
    }
}
